/*
 * @Author: xuetao 3168581151@qq.com
 * @Date: 2025-02-21
 * @LastEditors: xuetao 3168581151@qq.com
 * @LastEditTime: 2025-04-24
 * @Description: 
 */
import 'package:chat_client/enums/chat_enum.dart';
import 'package:chat_client/models/conversation_model.dart';
import 'package:chat_client/models/session_model.dart' show SessionModel;
import 'package:chat_client/repositories/auth_repository.dart'
    show AuthRepository;
import 'package:chat_client/repositories/conversation_repository.dart';
import 'package:chat_client/services/socket/conversation_service.dart';
import 'package:chat_client/utils/date_formater.dart' show checkTimeDifference;
import 'package:chat_client/utils/show_messae.dart' show popError;
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid_v4/uuid_v4.dart';

class ChatProvider extends ChangeNotifier {
  final ConversationRepository _chatRepository =
      ConversationRepository.instance;
  final ConversationService _conversationService = ConversationService.instance;
  final AuthRepository _authRepository = AuthRepository.instance;
  // 个人id
  late String _userId;

  // 输入框
  final TextEditingController _textController = TextEditingController();

  // 滚动控制器
  final ScrollController _scrollController = ScrollController();

  // 定位跟随
  final LayerLink _layerLink = LayerLink();

  // 未读消息数量
  int _unreadCount = 0;
  // 是否接近列表底部
  bool _isNearBottom = false;

  // 已加载的历史消息
  List<Message> _oldMessages = [];
  // 当前可视区域的新消息
  final List<Message> _newMessages = [];

  // 对话对象，contact / group
  late SessionModel _session;

  // 对外暴露
  TextEditingController get messageController => _textController;
  ScrollController get scrollController => _scrollController;
  LayerLink get layerLink => _layerLink;
  int get unreadCount => _unreadCount;
  bool get isNearBottom => _isNearBottom;
  String get userId => _userId;

  List<Message> get oldMessages => _oldMessages;
  List<Message> get newMessages => _newMessages;

  // 初始化
  ChatProvider(SessionModel session) {
    // 初始化会话
    _initConversation(session);
    // 注册滚动条监听器
    _scrollController.addListener(_scrollListener);
    // 注册消息接收逻辑
    _conversationService.addListenerMessageList(handleReceive);
    _conversationService
        .setCurrentChatSession(session.conversationId ?? session.id);
    // 初始化个人Id
    _userId = _authRepository.userSelfId;
  }

  @override
  void dispose() {
    _conversationService.removeListenerMessageList();
    _conversationService.removeCurrentChatSession();
    _scrollController.removeListener(_scrollListener);
    _scrollController.dispose();
    _textController.dispose();
    super.dispose();
  }

  // 初始化会话
  void _initConversation(SessionModel session) {
    _session = session;
    // 不存在本地会话
    if (session.conversationId == null) return;
    // 存在本地会话
    _oldMessages = _chatRepository
        .getConversationDetaile(session.conversationId!)
        .reversed
        .toList();
  }

  /// 滚动条监听器
  void _scrollListener() {
    final position = _scrollController.position;
    // 判断当前是否在距离底部 100px 范围内
    _isNearBottom = position.pixels >= position.maxScrollExtent - 100;

    // 当处于底部区域且有未读消息时，自动标记为已读
    if (_isNearBottom && _unreadCount > 0) {
      _unreadCount = 0; // 重置未读计数
    }
    notifyListeners();
  }

  /// 转跳至列表底部，并清空未读消息
  jumpToBottom() {
    _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
    _unreadCount = 0;
  }

  // -------------------------------------------------

  void handleSend(dynamic text) async {
    if (text.runtimeType == String) {
      sendTextMessage(text);
    } else if (text.runtimeType == XFile) {}
  }

  // 发送图片类消息

  // 发送文件类消息

  // 发送文本类消息
  void sendTextMessage(String text) async {
    try {
      if (text.isEmpty) return;

      // 创建本地临时消息
      final Map<String, String> sender = {'_id': _userId};
      final json = {'data': text, 'sender': sender};
      final Message message = Message.fromJson(json);

      // 检查是否创建时间点消息
      _addCenterTime();
      // 加入临时消息列组
      if (_session.type == ConversationType.user.value) {
        _newMessages.add(message);
      }
      // 发送消息
      _conversationService.sendMessage(message, _session);

      // 我方用户发送消息，立即滚动到底部
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
      });

      _textController.clear();
      notifyListeners();
    } catch (e) {
      popError(e.toString(), '发送失败');
      print(e);
    }
  }

  // 对方的消息回复
  Future<void> handleReceive(Message message) async {
    _addCenterTime();
    // 加入临时消息列组
    _newMessages.add(message);

    /// 判断是否需要显示未读气泡
    WidgetsBinding.instance.addPostFrameCallback((_) {
      final position = _scrollController.position;
      final maxScroll = position.maxScrollExtent;
      // 用户不在底部区域
      if (position.pixels < maxScroll - 60) {
        _unreadCount++;
      }
      // 用户已在底部区域
      else {
        _scrollController.jumpTo(maxScroll);
      }
    });
    notifyListeners();
  }

  _addCenterTime() {
    dynamic timestamp;
    // 新旧消息列表为空
    if (_oldMessages.isEmpty && _newMessages.isEmpty) {
      timestamp = null;
    }
    // 新消息为空
    else if (_newMessages.isEmpty) {
      timestamp = _oldMessages[_oldMessages.length - 1].sentAt;
    }
    // 新消息不为空
    else if (_newMessages.isNotEmpty) {
      timestamp = _newMessages[_newMessages.length - 1].sentAt;
    }
    final time = checkTimeDifference(timestamp: timestamp);
    if (time == null) return;
    // 创建本地time消息
    final json = {
      'data': time,
      'messageId': UUIDv4().toString(),
      'sender': null,
      'conversationId': _session.conversationId
    };

    final Message timeMessage = Message.fromJson(json);
    // 加入临时消息队列
    _newMessages.add(timeMessage);
    if (_session.conversationId != null) {
      _conversationService.storeMessage(timeMessage);
    }
  }
}
